package io.github.iogogogo.commons.collection;

import java.util.*;
import java.util.stream.IntStream;
import java.util.stream.Stream;

/**
 * Created by tao.zeng on 2024/11/7.
 */
public class FlatMapUtils {

    private FlatMapUtils() {
        throw new AssertionError("No instances for you!");
    }

    public static Map<String, Object> flatten(Map<String, Object> map) {
        return map.entrySet().stream()
                .flatMap(FlatMapUtils::flatten)
                .collect(LinkedHashMap::new, (m, e) -> m.put(String.join("", e.getKey()), e.getValue()), LinkedHashMap::putAll);
        // .collect(LinkedHashMap::new, (m, e) -> m.put(String.join("", "/", e.getKey()), e.getValue()), LinkedHashMap::putAll);
    }

    private static Stream<Map.Entry<String, Object>> flatten(Map.Entry<String, Object> entry) {

        if (Objects.isNull(entry)) return Stream.empty();

        if (entry.getValue() instanceof Map<?, ?>) {
            return ((Map<?, ?>) entry.getValue()).entrySet().stream()
                    .flatMap(e -> flatten(new AbstractMap.SimpleEntry<>(String.join(".$", entry.getKey(), String.valueOf(e.getKey())), e.getValue())));
        }

        if (entry.getValue() instanceof List<?>) {
            List<?> list = (List<?>) entry.getValue();
            return IntStream.range(0, list.size())
                    .mapToObj(i -> new AbstractMap.SimpleEntry<String, Object>(String.join(".$", entry.getKey(), String.valueOf(i)), list.get(i)))
                    .flatMap(FlatMapUtils::flatten);
        }
        return Stream.of(entry);
    }
}
